'use strict'

const { WHITE_LIST,LIMIT_LIST } = require('../config/url_config')


module.exports = (option, app) => {
    return async function (ctx, next) {

        const {app} = ctx;

        try {

            let request_path = ctx.request.path;
            let request_method = ctx.request.method;

            if(request_path == '/'){
                console.info("访问：",ctx.request.method,ctx.request.path);
                await next();
            }else{
                //遍历白名单
                let is_WHITE = WHITE_LIST.some((item,index)=>{
                    //如果请求是白名单，则直接通过
                    return app.lodash.startsWith(request_path,item.path);
                });

                //白名单 通过
                if(is_WHITE){
                    console.info("正在访问白名单：",ctx.request.method,ctx.request.path);
                    await next();
                }else{
                    //    非白名单，验证当前用户权限是否可通过
                    //    验证权限前，优先验证 是否是受限请求
                    let userInfo = await ctx.session.user_info;

                    //判空当前用户信息
                    if(!app.lodash.isEmpty(userInfo)){

                        //受限请求判断
                        let is_LIMIT = LIMIT_LIST.some((item,i)=>{
                            return app.lodash.startsWith(request_path,item.path) && request_method == item.method;
                        });

                        if (is_LIMIT){
                            console.info("正在访问受限名单：",ctx.request.method,ctx.request.path);
                            //受限请求 判断当前用户是否解除受限
                            let is_LIMIT_AUTH = LIMIT_LIST.some((item,i)=>{
                                return app.lodash.startsWith(request_path,item.path) && request_method == item.method && item.auth.indexOf(userInfo.rolename) > -1;
                            });

                            if(is_LIMIT_AUTH){
                                await next();
                            }else{
                                ctx.status = 200;
                                ctx.body = {
                                    code :403,
                                    error:'⚠️受限操作：当前用户不支持此操作！'
                                }
                            }
                        } else{
                            console.info("正在访问权限名单：",ctx.request.method,ctx.request.path);
                            //    非受限请求 权限判断
                            let auths = userInfo.auth;
                            //请求路径 与请求type 是否已配置
                            let is_AUTH = auths.some((item,i)=>{
                                return app.lodash.startsWith(request_path,item.path) && ( app.lodash.startsWith(item.code.toLowerCase(),'all') || request_method.toLowerCase() == item.code.toLowerCase() );
                            });

                            if(is_AUTH){
                                await next();
                            }else{
                                ctx.status = 200;
                                ctx.body = {
                                    code :401,
                                    error:'权限错误：当前角色未配置此权限！'
                                }
                            }
                        }
                    }else{
                        ctx.status = 200;
                        ctx.body = {
                            code :401,
                            error:'获取当前登录用户失败，可能当前登录已失效，请重新登录。'
                        }
                    }
                }
            }
        }catch (err) {
            // 所有的异常都在 app 上触发一个 error 事件，框架会记录一条错误日志
            app.emit('error', err, this)
            const status = err.status || 500
            // 生产环境时 500 错误的详细错误内容不返回给客户端，因为可能包含敏感信息
            const error = status === 500 && app.config.env === 'prod' ?
                'Internal Server Error' :
                err.message
            // 从 error 对象上读出各个属性，设置到响应中
            ctx.body = {
                code: status, // 服务端自身的处理逻辑错误(包含框架错误500 及 自定义业务逻辑错误533开始 ) 客户端请求参数导致的错误(4xx开始)，设置不同的状态码
                error: error
            }
            if (status === 422) {
                ctx.body.detail = err.errors
            }
            ctx.status = 200
        }
    }
}
